package org.pr.kafkaexpress.procedure;

import lombok.extern.slf4j.Slf4j;
import org.pr.kafkaexpress.constants.KafkaConstants;
import org.pr.kafkaexpress.exception.KafkaException;
import org.pr.kafkaexpress.util.MessageUtils;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.support.SendResult;
import org.springframework.stereotype.Component;

import java.util.concurrent.CompletableFuture;

/**
 * 消息生产者
 * 
 * @author LXC
 * @since 2025/7/10
 */
@Slf4j
@Component
public class MessageProducer {
    
    private final KafkaTemplate<String, String> kafkaTemplate;

    public MessageProducer(KafkaTemplate<String, String> kafkaTemplate) {
        this.kafkaTemplate = kafkaTemplate;
    }

    /**
     * 同步发送消息
     * 
     * @param topic 主题
     * @param message 消息内容
     */
    public void send(String topic, String message) {
        try {
            // 验证消息
            if (!MessageUtils.isValidMessage(message)) {
                throw new KafkaException("Invalid message: " + MessageUtils.formatMessageForLog(message, 100));
            }
            
            kafkaTemplate.send(topic, message);
            log.info("Message sent successfully to topic: {}, message: {}", 
                    topic, MessageUtils.formatMessageForLog(message, 100));
        } catch (Exception e) {
            log.error("Failed to send message to topic: {}, message: {}", 
                    topic, MessageUtils.formatMessageForLog(message, 100), e);
            throw new KafkaException(topic, message, e);
        }
    }

    /**
     * 异步发送消息
     * 
     * @param topic 主题
     * @param message 消息内容
     * @return CompletableFuture<SendResult<String, String>>
     */
    public CompletableFuture<SendResult<String, String>> sendAsync(String topic, String message) {
        try {
            CompletableFuture<SendResult<String, String>> future = kafkaTemplate.send(topic, message);
            future.whenComplete((result, throwable) -> {
                if (throwable != null) {
                    log.error("Failed to send message asynchronously to topic: {}, message: {}", topic, message, throwable);
                } else {
                    log.info("Message sent asynchronously to topic: {}, partition: {}, offset: {}", 
                            topic, result.getRecordMetadata().partition(), result.getRecordMetadata().offset());
                }
            });
            return future;
        } catch (Exception e) {
            log.error("Failed to send message asynchronously to topic: {}, message: {}", topic, message, e);
            throw new RuntimeException("Failed to send message asynchronously", e);
        }
    }

    /**
     * 发送消息到指定分区
     * 
     * @param topic 主题
     * @param partition 分区
     * @param key 消息键
     * @param message 消息内容
     */
    public void sendToPartition(String topic, int partition, String key, String message) {
        try {
            kafkaTemplate.send(topic, partition, key, message);
            log.info("Message sent to partition {} of topic: {}, key: {}, message: {}", 
                    partition, topic, key, message);
        } catch (Exception e) {
            log.error("Failed to send message to partition {} of topic: {}, key: {}, message: {}", 
                    partition, topic, key, message, e);
            throw new RuntimeException("Failed to send message to partition", e);
        }
    }
}
